package com.um.springboot.starter.orm.service;

import com.um.springboot.starter.dao.CommonDao;
import com.um.springboot.starter.entity.Page;
import com.um.springboot.starter.orm.dao.BaseEntityDao;
import com.um.springboot.starter.orm.entity.RangeEntity;
import com.um.springboot.starter.orm.params.ExportParams;
import com.um.springboot.starter.properties.HshProperties;
import com.um.springboot.starter.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ResourceUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 *
 * 接口端使用到的api
 * @author 邓南辉
 * 日期 2021/4/2
 * 版权所有 广州优匠科技有限公司
 */
@Slf4j
public class BaseEntityServiceImpl<M extends BaseEntityDao<T>,T> implements BaseEntityService<T> {

    @Autowired
    protected HshProperties hshProperties;

    @Autowired
    protected M dao;

    @Autowired
    protected CommonDao commonDao;

    protected Class<T> entityClass = this.currentEntityClass();


    public Class<T> getEntityClass() {
        return this.entityClass;
    }


    protected Class<T> currentEntityClass() {
        Type superclass = getClass().getGenericSuperclass();
        ParameterizedType type = (ParameterizedType) superclass;
        return (Class<T>) type.getActualTypeArguments()[1];
    }


    ///////////////////////////////保存操作///////////////////////////////////

    /**
     * 生成主键ID
     * @return
     */
    public String createUUIDPrimaryId(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }

    /**
     * 获得租户ID
     * @return
     */
    public String getComId(){
        return commonDao.getComId();
    }

    /**
     * 返回主键属性名称
     *
     * @return
     */
    private String getPrimaryPropertyName() {
        return NameUtils.getPropertyName(dao.getPrimaryName());
    }

    /**
     * 添加记录，饶开框架，不做历史记录
     */
    public boolean saveRecord(T entity) {

        String id = (String) ReflectUtil.getValue(entity, getPrimaryPropertyName());
        if (!StringUtil.getTrim(id).equals("")) {
            return dao.updateRecord(entity);
        } else {
            ReflectUtil.setValue(entity, getPrimaryPropertyName(), createUUIDPrimaryId());
            return dao.addRecord(entity);
        }
    }

    /**
     * 添加记录，饶开框架，不做历史记录
     */
    public boolean saveRow(T entity) {

        String id = (String) ReflectUtil.getValue(entity, getPrimaryPropertyName());
        if (!StringUtil.getTrim(id).equals("")) {
            return dao.updateRow(entity);
        } else {
            ReflectUtil.setValue(entity, getPrimaryPropertyName(), createUUIDPrimaryId());
            return dao.addRow(entity);
        }
    }

    /**
     * 插入一个实体,饶开框架，不添加com_id
     *
     * @param entity
     * @return
     */
    @Override
    public boolean addRow(T entity) {
        return dao.addRow(entity);
    }

    /**
     * 更新一个实体,饶开框架，不添加com_id
     *
     * @param entity
     * @return
     */
    @Override
    public boolean updateRow(T entity) {
        return dao.updateRow(entity);
    }

    /**
     * 按主键删除实体，饶开框架，不添加com_id
     *
     * @param id
     * @return
     */
    @Override
    public boolean deleteRow(String id) {
        return dao.deleteRow(id);
    }

    /**
     * 根据单个属性删除实体，饶开框架，不添加com_id
     *
     * @param property
     * @param value
     * @return
     */
    @Override
    public boolean deleteRow(String property, Object value) {
        return dao.deleteRow(property,value);
    }

    /**
     * 根据多个属生查询实体，饶开框架，不添加com_id
     *
     * @param properties
     * @param values
     * @return
     */
    @Override
    public boolean deleteRow(String[] properties, Object[] values) {
        return dao.deleteRow(properties,values);
    }

    /**
     * 根据主键查询实体，饶开框架，不添加com_id
     *
     * @param id
     * @return
     */
    @Override
    public T getRow(String id) {
        return dao.getRow(id);
    }

    /**
     * 根据单个属性查询实体，饶开框架，不添加com_id
     *
     * @param property
     * @param value
     * @return
     */
    @Override
    public T getRow(String property, Object value) {
        return dao.getRow(property,value);
    }

    /**
     * 根据多个属生查询实体，饶开框架，不添加com_id
     *
     * @param properties
     * @param values
     * @return
     */
    @Override
    public T getRow(String[] properties, Object[] values) {
        return dao.getRow(properties,values);
    }

    /**
     * 根据单个属性查询列表，饶开框架，不添加com_id
     *
     * @param property
     * @param value
     * @return
     */
    @Override
    public List<T> getRows(String property, Object value) {
        return dao.getRows(new String[]{property},new Object[]{value},new String[]{},new String[]{});
    }

    /**
     * 根据多个属生查询列表，饶开框架，不添加com_id
     *
     * @param property
     * @param value
     * @param orderName
     * @param sortNo
     * @return
     */
    @Override
    public List<T> getRows(String property, Object value, String orderName, String sortNo) {
        return  dao.getRows(new String[]{property},new Object[]{value},new String[]{orderName},new String[]{sortNo});
    }

    /**
     * 根据多个属生查询列表，饶开框架，不添加com_id
     *
     * @param properties
     * @param values
     * @return
     */
    @Override
    public List<T> getRows(String[] properties, Object[] values) {
        return  dao.getRows(properties,values,new String[]{},new String[]{});
    }

    /**
     * 根据多个属生查询列表，饶开框架，不添加com_id
     *
     * @param properties
     * @param values
     * @param orderName
     * @param sortNo
     * @return
     */
    @Override
    public List<T> getRows(String[] properties, Object[] values, String orderName, String sortNo) {
        return  dao.getRows(properties,values,new String[]{orderName},new String[]{sortNo});
    }

    /**
     * 插入一条数据，并返回自增ID
     *
     * @param entity 属性和值
     * @return 执行成功返回true
     */
    @Override
    public Long insert(T entity) {
        ReflectUtil.setValue(entity, getPrimaryPropertyName(), createUUIDPrimaryId());
        return dao.insert(entity);
    }

    /**
     * 保存一个对象,如果对象存在就更新，不存在就插入
     *
     * @param entity 属性和值
     * @return 执行成功返回true
     */
    @Override
    public boolean save(T entity) {
        String id = (String) ReflectUtil.getValue(entity, getPrimaryPropertyName());
        if (!StringUtil.getTrim(id).equals("")) {
            return dao.update(entity);
        } else {
            ReflectUtil.setValue(entity, getPrimaryPropertyName(), createUUIDPrimaryId());
            return dao.add(entity);
        }
    }


    /**
     * 保存一个对象,如果对象存在就更新，不存在就插入
     *
     * @param entity 属性和值
     * @return 返回保存后的实体Map
     */
    @Override
    public T saveEntity(T entity) {
        String id = (String) ReflectUtil.getValue(entity, getPrimaryPropertyName());
        if (!StringUtil.getTrim(id).equals("")) {
            dao.update(entity);
        } else {
            ReflectUtil.setValue(entity, getPrimaryPropertyName(), createUUIDPrimaryId());
            dao.add(entity);
        }
        return entity;
    }

    /**
     * 保存多个对象列表
     *
     * @param list 对象列表
     */
    @Override
    public boolean saveList(List<T> list) {
        boolean result = true;
        for (T entity : list) {
            String id = (String) ReflectUtil.getValue(entity, getPrimaryPropertyName());
            if (!StringUtil.getTrim(id).equals("")) {
                dao.update(entity);
            } else {
                ReflectUtil.setValue(entity, getPrimaryPropertyName(), createUUIDPrimaryId());
                result = result && dao.add(entity);
            }
        }
        return result;
    }

    /**
     * 插入一个对象
     *
     * @param entity 属性和值
     * @return 返回保存后的实体Map
     */
    @Override
    public boolean add(T entity) {
        return this.add(entity,true);
    }

    /**
     * 插入一个对象,不生成新的主键ID
     *
     * @param entity 属性和值
     * @return 返回保存后的实体Map
     */
    @Override
    public boolean add(T entity,boolean autoCreateId){
        if(autoCreateId) {
            ReflectUtil.setValue(entity, getPrimaryPropertyName(), createUUIDPrimaryId());
        }
        return dao.add(entity);
    }

    /**
     * 更改一个对象
     *
     * @param entity 实体Map
     */
    @Override
    public boolean update(T entity) {
        return dao.update(entity);
    }

    /**
     * 插入一个对象
     *
     * @param entity 属性和值
     * @return 返回保存后的实体Map
     */
    public T addEntity(T entity) {
        ReflectUtil.setValue(entity, getPrimaryPropertyName(), createUUIDPrimaryId());
        dao.add(entity);
        return entity;
    }

    /**
     * 更改一个对象
     *
     * @param entity 实体Map
     */
    @Override
    public T updateEntity(T entity) {
        dao.update(entity);
        return entity;
    }

    /**
     * 更新一个对象，可以设置更新空值
     * @param entity
     * @param updateNullProperties
     * @return
     */
    @Override
    public T updateEntity(T entity,String[] updateNullProperties){
        dao.update(entity,updateNullProperties);
        return entity;
    }

    /**
     * 删除一个列表
     *
     * @param list 实体列表
     * @return 执行成功返回true
     */
    @Override
    public boolean delete(List<T> list) {
        list.stream().forEach(item -> {
            dao.delete(item);
        });
        return true;
    }

    /**
     * 根据实体
     *
     * @param entity
     * @return 执行成功返回true
     */
    @Override
    public boolean delete(T entity) {
        return dao.delete(entity);
    }

    /**
     * 删除一个实体
     *
     * @param id
     * @return
     */
    @Override
    public boolean delete(String id) {
        return dao.delete(id);
    }

    /**
     * 根据一个属性删除对象
     *
     * @param property  属性名
     * @param value     值
     * @return 执行成功返回true
     */
    @Override
    public boolean delete(String property, Object value) {
        return dao.delete(property, value);
    }

    /**
     * 物量删除一个实体
     * @param property 属性名
     * @param value 属性值
     * @return
     */
    @Override
    public boolean deleteTrue(String property,Object value){
        return dao.deleteTrue(property,value);
    }

    /**
     * 物量删除一个实体
     *
     * @param properties 属性名
     * @param values     属性值
     * @return
     */
    @Override
    public boolean deleteTrue(String[] properties, Object[] values) {
        return dao.deleteTrue(properties,values);
    }

    /**
     * 根据指定属性删除对象
     *
     * @param properties 属性数组
     * @param values     值数组
     * @return 执行成功返回true
     */
    @Override
    public boolean delete(String[] properties, Object[] values) {
        return dao.delete(properties, values);
    }

    /**
     * 根据id列表删除对象
     *
     * @param ids 值数组
     * @return 执行成功返回true
     */
    @Override
    public boolean deleteIds(List<String> ids) {
        return dao.delete(ids);
    }

    /**
     * 查询一个对象
     *
     * @param properties 查询属性数组
     * @param values     查询属性值数组
     * @return 返回一个对象
     */
    @Override
    public T getEntity(String[] properties, Object[] values) {
        return dao.getEntity(properties,values);
    }

    /**
     * 查询一个对象
     *
     * @param property 查询属性
     * @param value    查询属性值
     * @return 返回一个对象
     */
    @Override
    public T getEntity(String property, Object value) {
        return dao.getEntity(property,value);
    }

    /**
     * 根据主键ID查询一个对象
     *
     * @param id 主键ID
     * @return 返回一个对象
     */
    @Override
    public T getEntity(String id) {
        return dao.getEntity(id);
    }

    /**
     * 查询一个对象，忽略逻辑删除
     *
     * @param properties 查询属性数组
     * @param values     查询属性值数组
     * @return 返回一个对象
     */
    @Override
    public T getRealEntity(String[] properties, Object[] values) {
        return dao.getRealEntity(properties,values);
    }

    /**
     * 查询一个对象，忽略逻辑删除
     *
     * @param property 查询属性
     * @param value    查询属性值
     * @return 返回一个对象
     */
    @Override
    public T getRealEntity(String property, Object value) {
        return dao.getRealEntity(property,value);
    }

    /**
     * 根据主键ID查询一个对象，忽略逻辑删除
     *
     * @param id 主键ID
     * @return 返回一个对象
     */
    @Override
    public T getRealEntity(String id) {
        return dao.getRealEntity(id);
    }

    /**
     * 根据自定义sql名称查询实体
     * @param sqlName sql名称
     * @param values 参数值
     * @return
     */
    @Override
    public T getEntityBySqlName(String sqlName,Object... values){
        return dao.getEntityBySqlName(sqlName,values);
    }

    /**
     * 根据自定义sql名称查询列表
     *
     * @param sqlName sql名称
     * @param clazz
     * @param values  参数值
     * @return
     */
    @Override
    public <M> M getViewModel(String sqlName, Class<M> clazz, Object[] values) {
        return dao.getViewModel(sqlName,clazz,values);
    }

    /**
     * 根据自定义sql查询列表
     *
     * @param sql sql
     * @param clazz
     * @param values  参数值
     * @return
     */
    @Override
    public <M> M getViewModelBySQL(String sql, Class<M> clazz, Object[] values) {
        return dao.getViewModelBySQL(sql,clazz,values);
    }

    /**
     * 查询所有列表
     *
     * @return
     */
    public List<T> getAll() {
        return dao.getAll();
    }

    /**
     * 根据单一属性查询列表
     *
     * @param property 属性
     * @param value    值
     * @return
     */
    public List<T> getList(String property, Object value) {
        return dao.getList(property, value);
    }

    /**
     * 根据单一属性查询列表，并指定单个排序条件
     *
     * @param property  属性
     * @param value     值
     * @param orderName 排序属性
     * @param sortOn    降序或升序
     * @return
     */
    public List<T> getList(String property, Object value, String orderName, String sortOn) {
        return dao.getList(property, value, orderName, sortOn);
    }

    /**
     * 根据多个属性查询指定列表
     *
     * @param properties 属性名称
     * @param values     属性值
     * @return 返回一个列表
     */
    public List<T> getList(String[] properties, Object[] values) {
        return dao.getList(properties, values);
    }

    /**
     * 根据多个属性查询指定列表
     *
     * @param properties 属性名称
     * @param values     属性值
     * @param orderNames 排序字段数组
     * @param sortOns    降序或升序数组
     * @return 返回一个列表
     */
    public List<T> getList(String[] properties, Object[] values, String[] orderNames, String[] sortOns) {
        return dao.getList(properties, values, orderNames, sortOns);
    }

    /**
     * 根据单一属性查询列表
     *
     * @param property 属性
     * @param value    值
     * @return
     */
    public List<T> getListByLike(String property, Object value) {
        return dao.getListByLike(property, value);
    }

    /**
     * 根据单一属性查询列表，并指定单个排序条件
     *
     * @param property  属性
     * @param value     值
     * @param orderName 排序属性
     * @param sortOn    降序或升序
     * @return
     */
    public List<T> getListByLike(String property, Object value, String orderName, String sortOn) {
        return dao.getListByLike(property, value, orderName, sortOn);
    }

    /**
     * 根据多个属性查询指定列表
     *
     * @param properties 属性名称
     * @param values     属性值
     * @return 返回一个列表
     */
    public List<T> getListByLike(String[] properties, Object[] values) {
        return dao.getListByLike(properties, values);
    }

    /**
     * 根据多个属性查询指定列表
     *
     * @param properties 属性名称
     * @param values     属性值
     * @param orderNames 排序字段数组
     * @param sortOns    降序或升序数组
     * @return 返回一个列表
     */
    public List<T> getListByLike(String[] properties, Object[] values, String[] orderNames, String[] sortOns) {
        return dao.getListByLike(properties, values, orderNames, sortOns);
    }

    /**
     * 根据多个属性查询指定列表
     *
     * @param properties 属性名称
     * @param values     属性值
     * @param rangs     属性值
     * @param orderNames 排序字段数组
     * @param sortOns    降序或升序数组
     * @return 返回一个列表
     */
    public List<T> getListByLike(String[] properties, Object[] values, List<RangeEntity> rangs,String[] orderNames, String[] sortOns) {
        return dao.getListByLike(properties, values,rangs, orderNames, sortOns);
    }

    /**
     * 根据多个属性查询列表，并指定多个排序条件
     *
     * @param properties 属性数组
     * @param values     值数组
     * @param ranges
     * @param orderNames 排序属性数据
     * @param sortOns    升降序数组
     * @param start
     * @param limit
     * @return
     */
    @Override
    public List<T> getListByLike(String[] properties, Object[] values, List<RangeEntity> ranges, String[] orderNames, String[] sortOns, int start, int limit) {
        return dao.queryList(properties,values,ranges,orderNames,sortOns,start,limit);
    }

    /**
     * 根据自定义sql名称查询列表
     *
     * @param sqlName sql名称
     * @param values  参数值
     * @return
     */
    public List<T> getListBySqlName(String sqlName, Object... values) {
        return dao.queryListBySqlName(sqlName, values);
    }

    /**
     * 根据自定义sql名称查询列表
     *
     * @param sqlName sql名称
     * @param values  命名参数值
     * @return
     */
    @Override
    public List<T> getListByNpSqlName(String sqlName, Map<String, ?> values) {
        return dao.queryListByNpSqlName(sqlName, values);
    }

    /**
     * 根据自定义sql查询列表
     *
     * @param sql    sql语句
     * @param values 参数值
     * @return
     */
    public List<T> getListBySql(String sql, Object... values) {
        return dao.queryListBySql(sql, values);
    }

    /**
     * 根据自定义sql查询列表
     *
     * @param sql    sql语句
     * @param values 命名参数值
     * @return
     */
    @Override
    public List<T> getListByNpSql(String sql, Map<String, ?> values) {
        return dao.queryListByNpSql(sql, values);
    }

    /**
     * 根据自定义sql名称查询列表
     *
     * @param sqlName sql名称
     * @param clazz
     * @param values  参数值
     * @return
     */
    @Override
    public <M> List<M> getViewModelList(String sqlName, Class<M> clazz, Object[] values) {
        return dao.getViewModelList(sqlName,clazz,values);
    }

    /**
     * 根据自定义sql名称查询列表
     *
     * @param sqlName sql名称
     * @param clazz
     * @param values  命名参数值
     * @return
     */
    @Override
    public <M> List<M> getViewModelListByNpSqlName(String sqlName, Class<M> clazz, Map<String, ?> values) {
        return dao.getViewModelListByNpSqlName(sqlName, clazz, values);
    }

    /**
     * 根据自定义sql查询列表
     * @param sql sql
     * @param clazz
     * @param values 参数值
     * @return
     */
    @Override
    public <M> List<M> getViewModelListBySQL(String sql, Class<M> clazz, Object[] values) {
        return dao.getViewModelListBySQL(sql,clazz,values);
    }

    /**
     * 根据自定义sql查询列表
     *
     * @param sql    sql
     * @param clazz
     * @param values 命名参数值
     * @return
     */
    @Override
    public <M> List<M> getViewModelListByNpSql(String sql, Class<M> clazz, Map<String, ?> values) {
        return dao.getViewModelListByNpSql(sql, clazz, values);
    }

    /**
     * 根据单一属性查询分页列表，并指定单个排序条件
     *
     * @param page      分页对象
     * @param property  属性名
     * @param value     值
     * @param orderName 排序属性数据
     * @param sortOn    升降序数组
     * @return
     */
    public Page<T> getPage(Page page, String property, Object value, String orderName, String sortOn) {
        return dao.queryPage(page, property, value, orderName, sortOn);
    }

    /**
     * 根据单一属性查询分页列表，并指定多个排序条件
     *
     * @param page       分页对象
     * @param property   属性名
     * @param value      值
     * @param orderNames 排序属性数据
     * @param sortOns    升降序数组
     * @return
     */
    public Page<T> getPage(Page page, String property, Object value, String[] orderNames, String[] sortOns) {
        return dao.queryPage(page, property, value, orderNames, sortOns);
    }

    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     *
     * @param page       分页对象
     * @param properties 属性数组
     * @param values     值数组
     * @param orderNames 排序属性数据
     * @param sortOns    升降序数组
     * @return
     */
    public Page<T> getPage(Page page, String[] properties, Object[] values, String[] orderNames, String[] sortOns) {
        return dao.queryPage(page, properties, values, orderNames, sortOns);
    }

    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     *
     * @param page         分页对象
     * @param properties   属性数组
     * @param values       值数组
     * @param orProperties or 条件属性数组
     * @param orValues     or 条件值数组
     * @param orderNames   排序属性数据
     * @param sortOns      升降序数组
     * @return
     */
    @Override
    public Page<T> queryPage(Page page, String[] properties, Object[] values, String[] orProperties, Object[] orValues, String[] orderNames, String[] sortOns) {
        return dao.queryPage(page, properties, values,orProperties,orValues, orderNames, sortOns);
    }

    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     * @param page  分页对象
     * @param properties  属性数组
     * @param values 值数组
     * @param range 范围条件对象
     * @param orderNames 排序属性数据
     * @param sortOns 升降序数组
     * @return
     */
    public Page<T> getPage(Page page, String[] properties, Object[] values, RangeEntity range, String[] orderNames, String[] sortOns){
        return dao.queryPage(page, properties, values,range, orderNames, sortOns);
    }

    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     * @param page  分页对象
     * @param properties  属性数组
     * @param values 值数组
     * @param ranges 范围条件对象
     * @param orderNames 排序属性数据
     * @param sortOns 升降序数组
     * @return
     */
    public Page<T> getPage(Page page, String[] properties, Object[] values,List<RangeEntity> ranges, String[] orderNames, String[] sortOns){
        return dao.queryPage(page, properties, values,new String[]{},new Object[]{},ranges, orderNames, sortOns);
    }

    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     * @param page  分页对象
     * @param properties  属性数组
     * @param values 值数组
     * @param orProperties  or 条件属性数组
     * @param orValues or 条件值数组
     * @param ranges 范围条件对象
     * @param orderNames 排序属性数据
     * @param sortOns 升降序数组
     * @return
     */
    public Page<T> getPage(Page page, String[] properties, Object[] values, String[] orProperties, Object[] orValues,List<RangeEntity> ranges, String[] orderNames, String[] sortOns){
        return dao.queryPage(page, properties, values,orProperties,orValues,ranges, orderNames, sortOns);
    }

    /**
     * 根据自定义sql名称分页查询列表
     * @param page 分页对象
     * @param sqlName sql列表名称
     * @param sqlCountName sql总条数名称
     * @param values 参数值
     * @return
     */
    public Page<T> getPageBySqlName(Page page,String sqlName,String sqlCountName,Object[] values){
        return dao.queryPageBySqlName(page,sqlName,sqlCountName,values);
    }

    /**
     * 根据自定义sql名称分页查询列表
     * @param page 分页对象
     * @param sql 列表sql
     * @param sqlCount 总条数sql
     * @param values 参数值
     * @return
     */
    public Page<T> getPageBySql(Page page,String sql,String sqlCount,Object[] values){
        return dao.queryPageBySql(page,sql,sqlCount,values);
    }

    /**
     * 根据自定义sql分页查询列表
     *
     * @param page         分页对象
     * @param sql      sql列表名称
     * @param sqlCount sql总条数名称
     * @param clazz
     * @param values       参数值
     * @return
     */
    @Override
    public <M> Page<M> getViewModelPageBySql(Page page, String sql, String sqlCount, Class<M> clazz, Object[] values) {
        return dao.getViewModelPageBySql(page,sql,sqlCount,clazz,values);
    }

    /**
     * 根据自定义sql名称分页查询列表
     *
     * @param page         分页对象
     * @param sqlName      sql列表名称
     * @param sqlCountName sql总条数名称
     * @param clazz
     * @param values       参数值
     * @return
     */
    @Override
    public <M> Page<M> getViewModelPageBySqlName(Page page, String sqlName, String sqlCountName, Class<M> clazz, Object[] values) {
        return dao.getViewModelPageBySqlName(page,sqlName,sqlCountName,clazz,values);
    }

    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     * @param properties  属性数组
     * @param values 值数组
     * @param ranges 范围条件对象
     * @return
     */
    @Override
    public <M> M getCMSViewModelBySqlName(String sqlName,Class<M> clazz,String[] properties, Object[] values, List<RangeEntity> ranges){
        return dao.getCMSViewModelBySqlName(sqlName,clazz,properties,values,ranges);
    }

    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     * @param properties  属性数组
     * @param values 值数组
     * @param ranges 范围条件对象
     * @return
     */
    @Override
    public <M> M getCMSViewModelBySqlName(String sqlName,Class<M> clazz,String[] properties, Object[] values, List<RangeEntity> ranges,Object[] params){
        return dao.getCMSViewModelBySqlName(sqlName,clazz,properties,values,ranges,params,true);
    }

    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     * @param properties  属性数组
     * @param values 值数组
     * @param ranges 范围条件对象
     * @return
     */
    @Override
    public <M> M getCMSViewModelBySqlName(String sqlName,Class<M> clazz,String[] properties, Object[] values, List<RangeEntity> ranges,Object[] params,boolean paramsAfterCondition){
        return dao.getCMSViewModelBySqlName(sqlName,clazz,properties,values,ranges,params,paramsAfterCondition);
    }

    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     * @param page  分页对象
     * @param properties  属性数组
     * @param values 值数组
     * @param ranges 范围条件对象
     * @param orderNames 排序属性数据
     * @param sortOns 升降序数组
     * @return
     */
    @Override
    public <M> Page<M> getCMSViewModelPageBySqlName(Page page,String sqlName,String sumSqlName,Class<M> clazz,String[] properties, Object[] values, List<RangeEntity> ranges,String[] orderNames, String[] sortOns){
        return dao.getCMSViewModelPageBySqlName(page,sqlName,sumSqlName,clazz,properties,values,ranges,orderNames,sortOns);
    }

    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     * @param page  分页对象
     * @param properties  属性数组
     * @param values 值数组
     * @param orProperties  or 条件属性数组
     * @param orValues or 条件值数组
     * @param ranges 范围条件对象
     * @param orderNames 排序属性数据
     * @param sortOns 升降序数组
     * @return
     */
    @Override
    public <M> Page<M> getCMSViewModelPageBySqlName(Page page,String sqlName,String sumSqlName,Class<M> clazz,String[] properties, Object[] values,String[] orProperties, Object[] orValues, List<RangeEntity> ranges,String[] orderNames, String[] sortOns){
        return dao.getCMSViewModelPageBySqlName(page,sqlName,sumSqlName,clazz,properties,values,orProperties,orValues,ranges,orderNames,sortOns);
    }
    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     * @param page  分页对象
     * @param properties  属性数组
     * @param values 值数组
     * @param ranges 范围条件对象
     * @param orderNames 排序属性数据
     * @param sortOns 升降序数组
     * @param params 其他参数
     * @paramsAfter [condition]参数在params参数后面，还是前面
     * @return
     */
    @Override
    public <M> Page<M> getCMSViewModelPageBySqlName(Page page,String sqlName,String sumSqlName,Class<M> clazz,String[] properties, Object[] values,List<RangeEntity> ranges,String[] orderNames, String[] sortOns,Object[] params,boolean paramsAfterCondition){
        return dao.getCMSViewModelPageBySqlName(page,sqlName,sumSqlName,clazz,properties,values,new String[]{},new Object[]{},ranges,orderNames,sortOns,params,paramsAfterCondition);
    }




    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     * @param properties  属性数组
     * @param values 值数组
     * @param ranges 范围条件对象
     * @param orderNames 排序属性数据
     * @param sortOns 升降序数组
     * @return
     */
    public <M> List<M> getCMSViewModelListBySqlName(String sqlName,Class<M> clazz,String[] properties, Object[] values, List<RangeEntity> ranges,String[] orderNames, String[] sortOns){
        return dao.getCMSViewModelListBySqlName(sqlName,clazz,properties,values,ranges,orderNames,sortOns);
    }

    /**
     * 根据多个属性查询分页列表，并指定多个排序条件
     * @param properties  属性数组
     * @param values 值数组
     * @param ranges 范围条件对象
     * @return
     */
    public <M> List<M> getCMSViewModelListBySqlName(String sqlName,Class<M> clazz,String[] properties, Object[] values, List<RangeEntity> ranges,String[] orderNames, String[] sortOns,Object[] params) {
        return dao.getCMSViewModelListBySqlName(sqlName,clazz,properties,values,ranges,orderNames,sortOns,params);
    }

    /**
     *
     * @param sqlName
     * @param clazz
     * @param properties  属性数组
     * @param values 值数组
     * @param ranges
     * @param orderNames 排序属性数据
     * @param sortOns 升降序数组
     * @param params
     * @param paramsAfterCondition
     * @return
     * @param <M>
     */
    @Override
    public <M> List<M> getCMSViewModelListBySqlName(String sqlName, Class<M> clazz, String[] properties, Object[] values, List<RangeEntity> ranges, String[] orderNames, String[] sortOns, Object[] params, boolean paramsAfterCondition) {
        return dao.getCMSViewModelListBySqlName(sqlName,clazz,properties,values,ranges,orderNames,sortOns,params,paramsAfterCondition);
    }

    /**
     * 根据sql name查询Long类型结果
     * @param sqlName
     * @param values
     * @return
     */
    @Override
    public Long getCountBySqlName(String sqlName, Object[] values){
        return dao.queryCountBySqlName(sqlName, values);
    }

    /**
     * 根据sql name查询泛型结果
     * @param sqlName
     * @param values
     * @param requiredType
     * @return
     * @param <T>
     */
    @Override
    public <T> T getObjectBySqlName(String sqlName, Object[] values, Class<T> requiredType){
        return dao.queryObjectBySqlName(sqlName, values, requiredType);
    }

    /**
     * 根据sql name查询泛型结果
     * @param sql
     * @param values
     * @return
     */
    @Override
    public <T> T queryObjectBySql(String sql, Object[] values, Class<T> requiredType){
        return dao.queryObjectBySql(sql,values,requiredType);
    }

    /**
     * 查询最大的编码
     * @param column
     * @param prefix
     * @param bit
     * @return
     */
    @Override
    public String getMaxCode(String column,String prefix,int bit){
        return dao.getMaxCode(column,prefix,bit);
    }

    /**
     * 查询最大的编码
     * @param column
     * @param property
     * @param prefix
     * @param bit
     * @return
     */
    @Override
    public String getMaxCode(String column,String property,String prefix,int bit){
        return dao.getMaxCode(column,property,prefix,bit);
    }

    /**
     * 导出Excel
     * @param exportParams
     * @return
     */
    @Override
    public String exportPage(ExportParams exportParams) {

        List columns = exportParams.getColumns();
        List properties = exportParams.getFields();
        Map mapFormat = exportParams.getMapFormat();
        Map mapParam = exportParams.getMapParam();
        Map mapZero = exportParams.getMapZero();


        List list = dao.queryList(exportParams.getProperties(),exportParams.getValues(),exportParams.getRangeEntitys(),exportParams.getOrderNames(),exportParams.getSortOns(),exportParams.getStart(),exportParams.getLimit());

        String fileName = "Excel" + DateUtil.getDateString(new Date(), "yyyyMMddHHmmss") + ".xls";
        String path = this.getExportFilePath(fileName);
        ExcelUtil.writeEntity(path, columns, list, properties, mapParam, mapFormat, mapZero);
        return getDownFilePath(fileName);
    }


    /**
     * 获得导出文件路径，兼容jar打包方式和war打包方式
     * @param fileName 导出的文件名称
     * @return
     */
    @Override
    public String getExportFilePath(String fileName){
        String path = "";
        try{
            if(hshProperties.getConfig().getPackaging().equals("jar") || !hshProperties.getFile().isRelative()){
                path = hshProperties.getFile().getPath()+"/export/"+fileName;
            }else{
                path = ResourceUtils.getURL("classpath:").getPath()+"static"+hshProperties.getFile().getPath()+"/export/"+fileName;
            }
        }catch (Exception ex){
            log.error("", ex);
        }
        return path;
    }

    /**
     * 返回文件下载路径
     * @param fileName
     * @return
     */
    @Override
    public String getDownFilePath(String fileName) {

        String path = "/export/" + fileName;
        return path;
    }



    /**
     * 返回文件的绝对路径
     * @param path 目录名称
     * @param fileName 文件名称
     * @return
     */
    @Override
    public String getFilePath(String path,String fileName){
        String filePath = "";
        try{
            if(hshProperties.getConfig().getPackaging().equals("jar") || !hshProperties.getFile().isRelative()){
                filePath = hshProperties.getFile().getPath()+"/"+path+"/"+fileName;
            }else{
                filePath = ResourceUtils.getURL("classpath:").getPath()+"static"+hshProperties.getFile().getPath()+"/"+path+"/"+fileName;
            }
        }catch (Exception ex){
            log.error("", ex);
        }
        return filePath;
    }

    /**
     * 返回文件的绝对路径
     * @param path 文件路径
     * @return
     */
    @Override
    public String getFilePath(String path){
        String filePath = "";
        try{
            if(hshProperties.getConfig().getPackaging().equals("jar") || !hshProperties.getFile().isRelative()){
                filePath = hshProperties.getFile().getPath()+"/"+path;
                log.debug("filePath0:"+filePath);
            }else{
                filePath = ResourceUtils.getURL("classpath:").getPath()+"static"+hshProperties.getFile().getPath()+"/"+path;
                log.debug("filePath1:"+filePath);
            }
        }catch (Exception ex){
            log.error("", ex);
        }
        return filePath;
    }
}
